package com.terren.statistic.execute;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.terren.statistic.common.entity.Documents;
import com.terren.statistic.common.entity.SysConfig;
import com.terren.statistic.common.util.CommonUtil;
import com.terren.statistic.common.util.HttpClient;
import com.terren.statistic.common.util.LogUtil;
import com.terren.statistic.db.entity.KeyConfigImpala;
import com.terren.statistic.db.entity.KeyStatis;
import com.terren.statistic.db.entity.TopicStatis;
import com.terren.statistic.db.service.KeyConfigImpalaService;
import com.terren.statistic.db.service.KeyStatisService;
import com.terren.statistic.db.service.TopicStatisService;
import com.terren.statistic.execute.excel.DocExport2Excel;

public class GetKeywordStatistic {
	private static Logger logger = LogUtil.getLogger(GetKeywordStatistic.class);
	private ArrayList<Documents> docList = new ArrayList<Documents>();
	private String api = "http://[RIDXHOST]:[RIDXPORT]/s/v1/search?q=[KW]&ctype=[CTYPE]&ps=[PS]&pe=[PE]&p=1&field=title,content";
	private static final short OFFICIAL_SITE = 0;
	private static final short PORTAL_SITE = 1;
	private long totalUv = 0;
	private long totalPv = 0;
	private String fileFormat;

	KeyConfigImpalaService keyConfigImpalaService;
	KeyStatisService keyStatisService;
	TopicStatisService topicStatisService;

	public GetKeywordStatistic() {
		this.fileFormat = SysConfig.FILE_FORMAT;
		keyConfigImpalaService = CommonUtil.getBean(KeyConfigImpalaService.class);
		keyStatisService = CommonUtil.getBean(KeyStatisService.class);
		topicStatisService = CommonUtil.getBean(TopicStatisService.class);
	}

	public void getData(String keyword, String startDate, String endDate) {
		this.fileFormat = SysConfig.FILE_FORMAT;
		KeyConfigImpala kw = new KeyConfigImpala();
		kw.setKeyId(0);
		kw.setName(keyword);
		kw.setStartTime(startDate);
		kw.setEndTime(endDate);
		getDataForCtype(kw, OFFICIAL_SITE);
		getDataForCtype(kw, PORTAL_SITE);
	}

	public void getData(String startDate, String endDate) {
		KeyConfigImpala param = new KeyConfigImpala();
		param.setStartTime(startDate);
		param.setEndTime(endDate);
		try {
			List<KeyConfigImpala> kwList = keyConfigImpalaService.getKeywordsNew(param);
			for (KeyConfigImpala kw : kwList) {
				getDataForCtype(kw, OFFICIAL_SITE);
				getDataForCtype(kw, PORTAL_SITE);
			}
			writeSummaryFile(startDate, endDate);
			keyConfigImpalaService.updateKeywordStatus(param);
		} catch (Exception e) {
			logger.error("GetKeywordStatistic.getData(String startDate, String endDate) error " + e.getMessage());
		}
	}

	public void getData() {
		try {
			List<KeyConfigImpala> kwList = keyConfigImpalaService.getKeywordsNew(null);
			for (KeyConfigImpala kw : kwList) {
				getDataForCtype(kw, OFFICIAL_SITE);
				getDataForCtype(kw, PORTAL_SITE);
				writeSummaryFile(kw.getStartTime(), kw.getEndTime());
				keyConfigImpalaService.updateKeywordStatus(kw);
			}
		} catch (Exception e) {
			logger.error("GetKeywordStatistic.getData() error " + e.getMessage());
		}
	}

	public void writeSummaryFile(String startDate, String endDate) throws Exception {
		KeyConfigImpala param = new KeyConfigImpala();
		param.setStartTime(startDate);
		param.setEndTime(endDate);
		List<TopicStatis> tsList = topicStatisService.getTopicStatis(param);
		String fileName = SysConfig.OUTSIDE_PATH + "TopicStatis_" + startDate + "_" + endDate + ".csv";
		File txtFile = new File(fileName);
		if (mkdir(txtFile)) {
			// 用OutputStreamWriter 替代 FileWriter，解决写UTF8格式文件的问题
			// FileWriter fw = new FileWriter(nodesFile);
			OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(txtFile), "GBK");
			BufferedWriter bw = new BufferedWriter(fw);
			bw.append("话题").append(",").append("配置").append(",").append("官媒UV").append(",").append("门户UV").append(",")
					.append("合计").append(System.lineSeparator());
			for (TopicStatis ts : tsList) {
				int total = ts.getUvOfcType0() + ts.getUvOfcType1();
				bw.append(ts.getTopic()).append(",");
				bw.append(ts.getKwConfig()).append(",");
				bw.append("" + ts.getUvOfcType0()).append(",");
				bw.append("" + ts.getUvOfcType1()).append(",");
				bw.append("" + total).append(System.lineSeparator());
			}
			bw.close();
			fw.close();
		}

	}

	private String getDataByUrl(String url, String cTypeStr, String kw, String st, String et, int offset)
			throws Exception {
		kw = kw.replaceAll("（", "(").replaceAll("）", ")").replaceAll("＆", "&").replaceAll("｜", "|")
				.replaceAll("&\\|", "&").replaceAll("\\|&", "|").replaceAll("\\(\\|", "(").replaceAll("\\(&", "(")
				.replaceAll("\\|\\)", ")").replaceAll("&\\)", ")");
		url = url.replace("[RIDXHOST]", SysConfig.RIDX_HOST).replace("[RIDXPORT]", String.valueOf(SysConfig.RIDX_PORT))
				.replace("[KW]", URLEncoder.encode(kw, "UTF8")).replace("[CTYPE]", cTypeStr).replace("[PS]", st)
				.replace("[PE]", et);
		url += "&limit=1000&offset=" + offset;
		logger.info(url);
		HttpClient hc = new HttpClient(SysConfig.RIDX_HOST, SysConfig.RIDX_PORT);
		hc.setTimeout((short) 180);
		return hc.pageReader("GET", url, "");
	}

	private void getDataForCtype(KeyConfigImpala kw, short cType) {
		docList = new ArrayList<Documents>();
		long keyId = kw.getKeyId();
		String keyword = kw.getName();
		String startTime = kw.getStartTime();
		String endTime = kw.getEndTime();
		logger.info("Keyword: " + keyword + ", ctype: " + cType);
		try {
			long st = System.currentTimeMillis();
			String cTypeStr = String.valueOf(cType);
			int articles = 0;
			totalUv = 0;
			totalPv = 0;
			int offset = 0;
			// if(cType == 3 || cType == 4) {
			while (true) {
				try {
					String jsonStr = getDataByUrl(api, cTypeStr, keyword, startTime, endTime, offset);
					// System.out.println(jsonStr);
					JSONObject jObj = JSONObject.parseObject(jsonStr);
					articles = jObj.getIntValue("total");
					parseJson(jsonStr);
					offset += 1000;
					if (offset >= articles)
						break;
				} catch (SocketTimeoutException se) {
					logger.error("com.webterren.spider.util.HttpClient - SocketTimeoutException, Retry!" + se.getMessage());
					continue;
				}
			}
			long et = System.currentTimeMillis();
			logger.info("keyword: " + keyword + ", cType: " + cType + ", articles: " + articles + ", totalPv: "
					+ totalPv + ", totalUv: " + totalUv + ", usage: " + (et - st) / 1000 + "(s).");
			if (keyId > 0) {
				write2DB(keyId, cType, articles, totalUv);
			}
			if (fileFormat.equals("2")) {
				exportJson(cType, startTime, endTime, keyword);
			}else if (fileFormat.equals("3")) {
				exportHtml(cType, startTime, endTime, keyword);	
			}else if (fileFormat.equals("4")) {
				exportTxt(cType, startTime, endTime, keyword);
			}else {
				exportExcel(cType, startTime, endTime, keyword);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void write2DB(long keyId, short cType, int articles, long totalUv) throws Exception {
		KeyStatis keyStatis = new KeyStatis();
		keyStatis.setKeyId(keyId);
		keyStatis.setCtype(cType);
		keyStatis.setArticleCount(articles);
		keyStatis.setUv(totalUv);
		keyStatisService.addKeywordStatis(keyStatis);
		KeyConfigImpala param = new KeyConfigImpala();
		param.setKeyId(keyId);
		keyConfigImpalaService.updateKeywordExportStatus(param);
	}

	private void parseJson(String jsonStr) {
		JSONObject jsonObj = JSONObject.parseObject(jsonStr);
		JSONArray jArr = jsonObj.getJSONArray("documents");
		long uv = 0;
		long pv = 0;
		for (int i = 0; i < jArr.size(); i++) {
			Documents doc = JSON.toJavaObject(jArr.getJSONObject(i), Documents.class);
			docList.add(doc);
			uv += doc.getUv();
			pv += doc.getPv();
		}
		totalUv += uv;
		totalPv += pv;
	}

	private void exportExcel(int cType, String startTime, String endTime, String keyword) {
		String fileName = "_" + cType + "_" + startTime.replaceAll("\\-", "") + "_" + endTime.replaceAll("\\-", "");
		try {
			DocExport2Excel dee = new DocExport2Excel();
			dee.createExcel(docList, fileName, SysConfig.OUTSIDE_PATH);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void exportJson(int cType, String startTime, String endTime, String keyword) throws Exception {
		String result = "";
		String fileName = SysConfig.OUTSIDE_PATH +"file" + cType + "_" + startTime.replaceAll("\\-", "") + "_" + endTime.replaceAll("\\-", "")
				+ ".json";
		File htmlFile = new File(fileName);
		OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8");
		BufferedWriter bw = new BufferedWriter(fw);
		try {
			ObjectMapper mapper = new ObjectMapper();
			mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
			result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(docList);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		bw.append(result);
		bw.close();
		fw.close();
	}

	private void exportHtml(int cType, String startTime, String endTime, String keyword) throws Exception {
		String fileName = SysConfig.OUTSIDE_PATH +"file" + cType + "_" + startTime.replaceAll("\\-", "") + "_" + endTime.replaceAll("\\-", "")
				+ ".html";
		File htmlFile = new File(fileName);
		// 用OutputStreamWriter 替代 FileWriter，解决写UTF8格式文件的问题
		// FileWriter fw = new FileWriter(nodesFile);
		OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8");
		BufferedWriter bw = new BufferedWriter(fw);
		bw.append("<!DOCTYPE HTML>");
		bw.append("<html>");
		bw.append("<head>");
		bw.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
		bw.append("<title>" + keyword + "相关新闻</title>");
		bw.append("</head>");
		bw.append("<body>");
		for (Documents doc : docList) {
			bw.append("<div>");
			String title = "<a href=\"[URL]\"><h1>[TITLE]</h1></a>";
			bw.append(title.replace("[URL]", doc.getUrl()).replace("[TITLE]", doc.getTitle()));
			String pubTimeSource = "<div><span>[PUBTIME]</span><span>[SOURCE]</span></div>";
			bw.append(pubTimeSource.replace("[PUBTIME]", doc.getPublishDay()).replace("[SOURCE]", doc.getCustomer()));
			String pvUv;
			if (cType == 0)
				pvUv = "<div><span>浏览量：[PV]&nbsp;&nbsp;</span><span>访客数：[UV]</span></div>";
			else if (cType == 1)
				pvUv = "<div><span>参与数：[PV]&nbsp;&nbsp;</span><span>评论数：[UV]</span></div>";
			else if (cType == 8)
				pvUv = "<div><span>阅读数：[PV]&nbsp;&nbsp;</span><span>点赞数：[UV]</span></div>";
			else
				pvUv = "<div><span></span><span></span></div>";
			bw.append(pvUv.replace("[PV]", "" + doc.getPv()).replace("[UV]", "" + doc.getUv()));
			bw.append("<p>");
			bw.append(doc.getContent());
			bw.append("</p>");
			bw.append("</div>");
			bw.append("</br>");
		}
		bw.append("</body>");
		bw.close();
		fw.close();
	}

	private boolean mkdir(File filePath) {
		// 判断目标文件所在的目录是否存在
		if (!filePath.getParentFile().exists()) {
			// 如果目标文件所在的目录不存在，则创建父目录
			if (!filePath.getParentFile().mkdirs()) {
				logger.error("mkdir " + filePath + " failed!");
				return false;
			}
		}
		return true;
	}

	private void exportTxt(int cType, String startTime, String endTime, String keyword) throws Exception {
		for (Documents doc : docList) {
			String exportPath = SysConfig.OUTSIDE_PATH + cType + "/" + startTime.substring(0, 7);
			String fileName = exportPath + "/" + CommonUtil.getSingleId() + ".txt";
			File txtFile = new File(fileName);
			if (mkdir(txtFile)) {
				// 用OutputStreamWriter 替代 FileWriter，解决写UTF8格式文件的问题
				// FileWriter fw = new FileWriter(nodesFile);
				OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(txtFile), "UTF-8");
				BufferedWriter bw = new BufferedWriter(fw);
				bw.append("关键词：");
				bw.append(keyword);
				bw.append(System.lineSeparator());
				bw.append("内容格式：");
				if (cType == 0)
					bw.append("标题 ||| 链接 ||| 发布时间 ||| 来源 ||| 浏览量 ||| 访客数 ||| 正文内容");
				else if (cType == 1)
					bw.append("标题 ||| 链接 ||| 发布时间 ||| 来源 ||| 参与数 ||| 评论数 ||| 正文内容");
				else if (cType == 8)
					bw.append("标题 ||| 链接 ||| 发布时间 ||| 来源 ||| 阅读数 ||| 点赞数 ||| 正文内容");
				else
					bw.append("标题 ||| 链接 ||| 发布时间 ||| 来源 ||| - ||| - ||| 正文内容");

				bw.append(System.lineSeparator());
				String format = "[TITLE]|||[URL]|||[PUBTIME]|||[SOURCE]|||[PV]|||[UV]|||[CONTENT]";
				String text = format.replace("[TITLE]", doc.getTitle()).replace("[URL]", doc.getUrl())
						.replace("[PUBTIME]", doc.getPublishDay()).replace("[SOURCE]", doc.getCustomer())
						.replace("[PV]", "" + doc.getPv()).replace("[UV]", "" + doc.getUv())
						.replace("[CONTENT]", doc.getContent() == null ? "" : doc.getContent());
				bw.append(text);
				bw.close();
				fw.close();
			}
		}
	}
	
}
